package tw.com.hitevision.whiteboard.android.andServer;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.pdf.PdfDocument;
import android.os.Environment;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.RectangleReadOnly;
import com.itextpdf.text.pdf.PdfWriter;
import com.yanzhenjie.andserver.AndServer;
import com.yanzhenjie.andserver.Server;
import com.yanzhenjie.andserver.filter.HttpCacheFilter;
import com.yanzhenjie.andserver.website.StorageWebsite;
import com.yanzhenjie.andserver.website.WebSite;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import androidx.annotation.Nullable;
import tw.com.hitevision.whiteboard.android.BuildConfig;
import tw.com.hitevision.whiteboard.android.Props;
import tw.com.hitevision.whiteboard.android.R;
import tw.com.hitevision.whiteboard.android.storage.FileHelper;
import tw.com.hitevision.whiteboard.android.widgets.NavigatorViewQRCodeExportDialog;

public class ServerService extends Service {

    private static final String TAG = "ServerService";
    public static final String FILE_FORMAT_INTENT_KEY = "FileFormatIntentKey";
    public static final String FILE_PATH_INTENT_KEY = "FilePathIntentKey";
    public static final String FILE_TIMESTAMP_INTENT_KEY = "FileTimeStampKey";
    private String screenshotFolderPath;

    private final int PDF_WIDTH = 1920;
    private final int PDF_HEIGHT = 1080;
    private String timeStamp;
    private File saveFolder;
    private Server server;
//    private Thread createPDFThread;
    private ExecutorService threadPool = Executors.newScheduledThreadPool(1);
    private Deque<String> deleteJpegList = new ArrayDeque<>();

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate");
        if(Props.getFlavorChipset().equals(Props.Flavor.Chipset.Hisi)){
            screenshotFolderPath = FileHelper.FOLDER_SCREENSHOTS_19C;
        }else{
            screenshotFolderPath = FileHelper.FOLDER_SCREENSHOTS;
        }

        if(Props.getMainboardVersion() == Props.Mainboard.V_828 && BuildConfig.BUILD_TYPE.equals("release")) {
            saveFolder = new File("/storage/sdcard0/" + screenshotFolderPath);
        } else {
            saveFolder = new File(Environment.getExternalStorageDirectory().getPath() + screenshotFolderPath);
        }

        Log.d(TAG, "onCreate saveFolder:" + saveFolder.getAbsolutePath());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
//        int fileFormat = intent.getIntExtra(FILE_FORMAT_INTENT_KEY, 0);
        int pos = intent.getIntExtra(FILE_FORMAT_INTENT_KEY, 0);
        timeStamp = intent.getStringExtra(FILE_TIMESTAMP_INTENT_KEY) + ".pdf";
        NavigatorViewQRCodeExportDialog.FileFormat fileFormat = NavigatorViewQRCodeExportDialog.FileFormat.values()[pos];
        Log.d(TAG, "onStartCommand fileFormat:" + fileFormat);
        threadPool.execute(() -> {
            createHtmlFile(fileFormat, intent.getStringArrayListExtra(FILE_PATH_INTENT_KEY));
            if(fileFormat == NavigatorViewQRCodeExportDialog.FileFormat.PNG || fileFormat == NavigatorViewQRCodeExportDialog.FileFormat.JPEG) {
                setupWebServer();
            } else {
                createPDFImage();
                setupDownloadServer();
            }
            startServer();
        });
//        createPDFThread = new Thread(()->{
//            createHtmlFile(fileFormat, intent.getStringArrayListExtra(FILE_PATH_INTENT_KEY));
//            if(fileFormat == 0) {
//                setupWebServer();
//            } else {
//                createPDFImage();
//                setupDownloadServer();
//            }
//            startServer();
//        });
//        createPDFThread.start();
        return START_REDELIVER_INTENT;
    }

    private void createHtmlFile(NavigatorViewQRCodeExportDialog.FileFormat fileFormat, ArrayList<String> fileList) {
        Log.d(TAG, "createHtmlFile fileFormat:" + fileFormat + " ,fileList:" + fileList);
        String downloadHtmlName = "download.html";
        File htmlFile = new File(saveFolder, downloadHtmlName);
        switch (fileFormat) {
            case PNG:{
                // crate png download html
                try {
                    FileOutputStream out = new FileOutputStream(htmlFile);
                    byte[] data = createPNGDownloadHTML(fileList).toString().getBytes();
                    out.write(data);
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "Save " + downloadHtmlName + " fail:" + e.getMessage());
                }
                // create png index html
                createIndexHTML(downloadHtmlName);
                break;
            }
            case JPEG:{
                // crate png download html
                try {
                    ArrayList<String> jpegFileList = new ArrayList<>();
//                    try {
//                        FileOutputStream out = new FileOutputStream(filename);
//                        bmp.compress(Bitmap.CompressFormat.PNG, 100, out); //100-best quality
//                        out.close();
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
                    FileHelper fileHelper = FileHelper.getInstance(this);
                    for (String s : fileList) {
                        File preview = fileHelper.getPreviewFile(s);
                        String path = preview.getAbsolutePath();
                        Bitmap bitmap = BitmapFactory.decodeFile(path);
                        if (bitmap != null) {
                            String jpegPath = path.substring(0, path.lastIndexOf(".")) + ".jpeg";
                            Log.d(TAG, "create jpeg : " + jpegPath);
                            File file = new File(jpegPath);
                            if (!file.exists()) {
                                file.createNewFile();
                            }
                            FileOutputStream out = new FileOutputStream(file);
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                            jpegFileList.add(jpegPath);
                            deleteJpegList.add(jpegPath);
//                            MediaScannerConnection.scanFile(this, new String[] {file.getPath()}, null, new MediaScannerConnection.OnScanCompletedListener() {
//                                @Override
//                                public void onScanCompleted(String path, Uri uri) {
//                                    syncFile(ServerService.this, uri);
//                                }
//                            });
                        }
                    }
                    FileOutputStream out = new FileOutputStream(htmlFile);
                    byte[] data = createPNGDownloadHTML(jpegFileList).toString().getBytes();
                    out.write(data);
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "Save " + downloadHtmlName + " fail:" + e.getMessage());
                }
                // create png index html
                createIndexHTML(downloadHtmlName);
                break;
            }
            case PDF:{
                if(Props.getMainboardVersion() == Props.Mainboard.V_828 && BuildConfig.BUILD_TYPE.equals("release")) {
                    createPDFFilewithItex(fileList);
                } else {
                    createPDFFile(fileList);
                }

                try {
                    FileOutputStream out = new FileOutputStream(htmlFile);
                    byte[] data = createPDFDownloadHTML().toString().getBytes();
                    out.write(data);
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "Save " + downloadHtmlName + " fail:" + e.getMessage());
                }
                // create pdf index html
                createIndexHTML(downloadHtmlName);
                break;
            }
        }
        Log.d(TAG, "htmlFile path:" + htmlFile.getAbsolutePath());
    }

    private void createPDFFilewithItex(ArrayList<String> fileList) {
        Rectangle rectangle = new RectangleReadOnly(PDF_WIDTH,PDF_HEIGHT);
        Document document = new Document(rectangle, 0f, 0f, 0f, 0f);
        String directoryPath = saveFolder.getAbsolutePath();
        try {
            PdfWriter.getInstance(document, new FileOutputStream(directoryPath + String.format("/image/%s", timeStamp)));
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
            Log.i(TAG, "create example pdf exception:" + e.getMessage());
        }
        document.open();

        for(String path: fileList) {
            Image image = null;
            try {
                image = Image.getInstance(directoryPath + "/image/" + path);
            } catch (BadElementException | IOException e) {
                e.printStackTrace();
                Log.e(TAG, "open " + path + " image pdf exception:" + e.getMessage());
            }
            if(image!=null) {
                float scale = ((document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin() - 0) / image.getWidth()) * 100;
                image.scalePercent(scale);
                image.setAlignment(Image.ALIGN_CENTER);
            }
            try {
                document.add(image);
            } catch (DocumentException e) {
                e.printStackTrace();
                Log.e(TAG, "add " + path + " image to pdf exception:" + e.getMessage());
            }
        }
        document.close();
        File pdf_file = new File(saveFolder.getAbsolutePath() + String.format("/image/%s", timeStamp));
        Log.i(TAG, "createPDFFile " + pdf_file.getName() + " is successful");
    }

    private void setupWebServer() {
        Log.d(TAG, "setupWebServer");

        File temp = new File(Environment.getExternalStorageDirectory(), screenshotFolderPath);
        String websiteDirectory = temp.getAbsolutePath();
        WebSite webSite = new StorageWebsite(websiteDirectory);

        server = AndServer.serverBuilder()
                .inetAddress(NetUtils.getLocalIPAddress())
                .port(NetUtils.PORT_SERVER)
                .timeout(10, TimeUnit.SECONDS)
                .website(webSite)
                .filter(new HttpCacheFilter())
                .listener(new Server.ServerListener() {
                    @Override
                    public void onStarted() {
                        String hostAddress = server.getInetAddress().getHostAddress();
                        Log.e(TAG, "onStarted : " + hostAddress);
                        ServerPresenter.onServerStarted(ServerService.this, hostAddress);
                    }

                    @Override
                    public void onStopped() {
                        Log.e(TAG, "onStopped");
                        ServerPresenter.onServerStopped(ServerService.this);
                    }

                    @Override
                    public void onError(Exception e) {
                        Log.e(TAG, "onError : " + e.getMessage());
                        ServerPresenter.onServerError(ServerService.this, e.getMessage());
                    }
                })
                .build();
    }

    private void setupDownloadServer() {
        Log.d(TAG, "setupDownloadServer");

        File temp = new File(Environment.getExternalStorageDirectory(), screenshotFolderPath);
        String websiteDirectory = temp.getAbsolutePath();
        WebSite webSite = new StorageWebsite(websiteDirectory);

        File file = new File(Environment.getExternalStorageDirectory(), screenshotFolderPath + "/image/"+timeStamp);
        server = AndServer.serverBuilder()
                .inetAddress(NetUtils.getLocalIPAddress())
                .port(NetUtils.PORT_SERVER)
                .timeout(10, TimeUnit.SECONDS)
                .registerHandler("/download", new DownloadPDFHandler(file))
                .website(webSite)
                .filter(new HttpCacheFilter())
                .listener(new Server.ServerListener() {
                    @Override
                    public void onStarted() {
                        String hostAddress = server.getInetAddress().getHostAddress();
                        Log.e(TAG, "onStarted : " + hostAddress);
                        ServerPresenter.onServerStarted(ServerService.this, hostAddress);
                    }

                    @Override
                    public void onStopped() {
                        Log.e(TAG, "onStopped");
                        ServerPresenter.onServerStopped(ServerService.this);
                    }

                    @Override
                    public void onError(Exception e) {
                        Log.e(TAG, "onError : " + e.getMessage());
                        ServerPresenter.onServerError(ServerService.this, e.getMessage());
                    }
                })
                .build();
    }

    private void startServer() {
        if (server.isRunning()) {
            InetAddress inetAddress = server.getInetAddress();
            if (inetAddress != null) {
                String hostAddress = inetAddress.getHostAddress();
                if (!TextUtils.isEmpty(hostAddress)) {
                    ServerPresenter.onServerStarted(ServerService.this, hostAddress);
                }
            }
        } else {
            server.startup();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return null;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
//        if(createPDFThread.isAlive()) { createPDFThread.interrupt(); }

        threadPool.shutdown();
        deleteHTMLFile();
        deletePDFFile();
        deletePDFImage();
        setDeleteJpegFile();
        stopServer();
    }

    private void stopServer() {
        if (server != null && server.isRunning()) {
            server.shutdown();
        }
    }

    private StringBuilder createPNGDownloadHTML(ArrayList<String> fileList) {
        StringBuilder png_download_html = new StringBuilder()
                .append("<!DOCTYPE html>\n")
                .append("<html>\n")
                .append("    <head>\n")
                .append("        <meta content=\"text/html; charset=UTF-8\" http-equiv=\"content-type\">\n")
                .append("        <style type=\"text/css\">\n")
                .append("            #content {\n")
                .append("                text-align: center;\n")
                .append("                font-size:30px;\n")
                .append("                vertical-align: middle;\n")
                .append("                color: #000000;\n")
                .append("                background-color: #ffffff;\n")
                .append("                position: absolute;\n")
                .append("                top: 0px;\n")
                .append("                left: 0px;\n")
                .append("            }\n")
                .append("        </style>\n")
                .append("        <script type=\"text/javascript\">\n")
                .append("            window.onload = function(event) {\n")
                .append("                function style(obj, prop) {\n")
                .append("                    if(window.getComputedStyle) {\n")
                .append("                        return window.getComputedStyle(obj, null)[prop];\n")
                .append("                    }\n")
                .append("                    else if(obj.currentStyle) {\n")
                .append("                        return obj.currentStyle[prop];\n")
                .append("                    }\n")
                .append("                    else {\n")
                .append("                        return null;\n")
                .append("                    }\n")
                .append("                }            \n")
                .append("                function opacity(element, value) {\n")
                .append("                    if(value === undefined) { \n")
                .append("                        var opt = style(element, 'opacity') \n")
                .append("                                     || style(element, 'filter');\n")
                .append("                        if(opt === '') {\n")
                .append("                            return 1;\n")
                .append("                        }\n")
                .append("                        if(opt.indexOf('alpha') !== -1)  {\n")
                .append("                            return opt.substring(14, opt.length - 1) / 100;\n")
                .append("                        }\n")
                .append("                        return parseFloat(opt);\n")
                .append("                    }\n")
                .append("                \n")
                .append("                } \n")
                .append("           \n")
                .append("                function screenWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: screen.width,\n")
                .append("                        height: screen.height\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function screenAvailWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: screen.availWidth,\n")
                .append("                        height: screen.availHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function windowXY() {\n")
                .append("                    var xy = {};\n")
                .append("                    if(window.screenX) {\n")
                .append("                        xy.x = window.screenX;\n")
                .append("                        xy.y = window.screenY;\n")
                .append("                    }\n")
                .append("                    else if(window.screenLeft) {\n")
                .append("                        xy.x = window.screenLeft;\n")
                .append("                        xy.y = window.screenTop;\n")
                .append("                    }\n")
                .append("                    return xy;\n")
                .append("                }\n")
                .append("                function windowWidthHeight() {\n")
                .append("                    var wh = {};\n")
                .append("                    if(window.outerWidth) {\n")
                .append("                        wh.width = window.outerWidth;\n")
                .append("                        wh.height = window.outerHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.offsetWidth) {\n")
                .append("                        wh.width = document.documentElement.offsetWidth;\n")
                .append("                        wh.height = document.documentElement.offsetHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.body.offsetWidth) {\n")
                .append("                        wh.width = document.body.offsetWidth;\n")
                .append("                        wh.height = document.body.offsetHeight;\n")
                .append("                    }\n")
                .append("                    return wh;\n")
                .append("                }                \n")
                .append("                function htmlWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: window.documentElement.scrollWidth,\n")
                .append("                        height: window.documentElement.scrollHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function bodyWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: window.body.scrollWidth,\n")
                .append("                        height: window.body.scrollHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function viewPortWidthHeight() {\n")
                .append("                    var wh = {};\n")
                .append("                    if(window.innerWidth) {\n")
                .append("                        wh.width = window.innerWidth;\n")
                .append("                        wh.height = window.innerHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.clientWidth) {\n")
                .append("                        wh.width = document.documentElement.clientWidth;\n")
                .append("                        wh.height = document.documentElement.clientHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.body.clientWidth) {\n")
                .append("                        wh.width = document.body.clientWidth;\n")
                .append("                        wh.height = document.body.clientHeight;\n")
                .append("                    }\n")
                .append("                    return wh;\n")
                .append("                }\n")
                .append("                function scrollXY() {\n")
                .append("                    var xy = {};\n")
                .append("                    if(window.pageXOffset) {\n")
                .append("                        xy.x = window.pageXOffset;\n")
                .append("                        xy.y = window.pageYOffset;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.srollLeft) {\n")
                .append("                        xy.x = document.documentElement.srollLeft;\n")
                .append("                        xy.y = document.documentElement.srollTop;\n")
                .append("                    }\n")
                .append("                    else if(document.body.srollLeft) {\n")
                .append("                        xy.x = document.body.srollLeft;\n")
                .append("                        xy.y = document.body.srollTop;\n")
                .append("                    }\n")
                .append("                    return xy;\n")
                .append("                }\n")
                .append("                \n")
                .append("                var content = document.getElementById('content');\n")
                .append("                opacity(content, 0.5);\n")
                .append("                \n")
                .append("                var viewPortWH = viewPortWidthHeight();\n")
                .append("                \n")
                .append("                content.style.width = viewPortWH.width + 'px';\n")
                .append("                content.style.height = viewPortWH.height / 2 + 'px';\n")
                .append("            };\n")
                .append("        </script>        \n")
                .append("    </head>\n")
                .append("<body>\n")
                .append("<div id=\"content\">\n");

        for (String filePath : fileList) {
            String[] filePathSplit = filePath.split("/");
            String fileName = filePathSplit[filePathSplit.length - 1];
            png_download_html.append("<br></br>\n")
                    .append("    <a href=\"/image/").append(fileName).append("\" download>\n")
                    .append("        <img src=\"/image/").append(fileName).append("\" alt=\"\" width=\"769\" height=\"432\">\n")
                    .append("    </a>\n")
                    .append("    <h2>").append(fileName).append("</h2>")
                    .append("<br></br>\n");
        }
        png_download_html.append("</div>\n")
                .append("\n")
                .append("</body>\n")
                .append("</html>\n");

        return png_download_html;
    }

    private StringBuilder createPDFDownloadHTML() {
        StringBuilder pdf_download_html = new StringBuilder()
                .append("<!DOCTYPE html>\n")
                .append("<html>\n")
                .append("    <head>\n")
                .append("        <meta content=\"text/html; charset=UTF-8\" http-equiv=\"content-type\">\n")
                .append("        <style type=\"text/css\">\n")
                .append("            #content {\n")
                .append("                text-align: center;\n")
                .append("                font-size:30px;\n")
                .append("                vertical-align:middle;\n")
                .append("                color: #000000;\n")
                .append("                background-color: #ffffff;\n")
                .append("                position: absolute;\n")
                .append("                top: 0px;\n")
                .append("                left: 0px;\n")
                .append("            }\n")
                .append("            #viewButton {\n")
                .append("                background-color: #ffffff;\n")
                .append("                border: 2px solid #1f86eb;\n")
                .append("                border-radius: 10px;\n")
                .append("                text-align:center;\n")
                .append("                color:#1f86eb;\n")
                .append("                font-size:35px;\n")
                .append("                vertical-align: middle;\n")
                .append("                width: 230px;\n")
                .append("                height: 90px;\n")
                .append("            }\n")
                .append("            #downloadButton {\n")
                .append("                background-color: #1f86eb;\n")
                .append("                border: 2px solid #1f86eb;\n")
                .append("                border-radius: 10px;\n")
                .append("                text-align:center;\n")
                .append("                color:#ffffff;\n")
                .append("                font-size:35px;\n")
                .append("                vertical-align: middle;\n")
                .append("                width: 230px;\n")
                .append("                height: 90px;\n")
                .append("            }\n")
                .append("        </style>\n")
                .append("        <script type=\"text/javascript\">\n")
                .append("            window.onload = function(event) {\n")
                .append("                function style(obj, prop) {\n")
                .append("                    if(window.getComputedStyle) {\n")
                .append("                        return window.getComputedStyle(obj, null)[prop];\n")
                .append("                    }\n")
                .append("                    else if(obj.currentStyle) {\n")
                .append("                        return obj.currentStyle[prop];\n")
                .append("                    }\n")
                .append("                    else {\n")
                .append("                        return null;\n")
                .append("                    }\n")
                .append("                }            \n")
                .append("                function opacity(element, value) {\n")
                .append("                    if(value === undefined) { \n")
                .append("                        var opt = style(element, 'opacity') \n")
                .append("                                     || style(element, 'filter');\n")
                .append("                        if(opt === '') {\n")
                .append("                            return 1;\n")
                .append("                        }\n")
                .append("                        if(opt.indexOf('alpha') !== -1)  {\n")
                .append("                            return opt.substring(14, opt.length - 1) / 100;\n")
                .append("                        }\n")
                .append("                        return parseFloat(opt);\n")
                .append("                    }\n")
                .append("                \n")
                .append("                } \n")
                .append("           \n")
                .append("                function screenWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: screen.width,\n")
                .append("                        height: screen.height\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function screenAvailWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: screen.availWidth,\n")
                .append("                        height: screen.availHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function windowXY() {\n")
                .append("                    var xy = {};\n")
                .append("                    if(window.screenX) {\n")
                .append("                        xy.x = window.screenX;\n")
                .append("                        xy.y = window.screenY;\n")
                .append("                    }\n")
                .append("                    else if(window.screenLeft) {\n")
                .append("                        xy.x = window.screenLeft;\n")
                .append("                        xy.y = window.screenTop;\n")
                .append("                    }\n")
                .append("                    return xy;\n")
                .append("                }\n")
                .append("                function windowWidthHeight() {\n")
                .append("                    var wh = {};\n")
                .append("                    if(window.outerWidth) {\n")
                .append("                        wh.width = window.outerWidth;\n")
                .append("                        wh.height = window.outerHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.offsetWidth) {\n")
                .append("                        wh.width = document.documentElement.offsetWidth;\n")
                .append("                        wh.height = document.documentElement.offsetHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.body.offsetWidth) {\n")
                .append("                        wh.width = document.body.offsetWidth;\n")
                .append("                        wh.height = document.body.offsetHeight;\n")
                .append("                    }\n")
                .append("                    return wh;\n")
                .append("                }                \n")
                .append("                function htmlWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: window.documentElement.scrollWidth,\n")
                .append("                        height: window.documentElement.scrollHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function bodyWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: window.body.scrollWidth,\n")
                .append("                        height: window.body.scrollHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function viewPortWidthHeight() {\n")
                .append("                    var wh = {};\n")
                .append("                    if(window.innerWidth) {\n")
                .append("                        wh.width = window.innerWidth;\n")
                .append("                        wh.height = window.innerHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.clientWidth) {\n")
                .append("                        wh.width = document.documentElement.clientWidth;\n")
                .append("                        wh.height = document.documentElement.clientHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.body.clientWidth) {\n")
                .append("                        wh.width = document.body.clientWidth;\n")
                .append("                        wh.height = document.body.clientHeight;\n")
                .append("                    }\n")
                .append("                    return wh;\n")
                .append("                }\n")
                .append("                function scrollXY() {\n")
                .append("                    var xy = {};\n")
                .append("                    if(window.pageXOffset) {\n")
                .append("                        xy.x = window.pageXOffset;\n")
                .append("                        xy.y = window.pageYOffset;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.srollLeft) {\n")
                .append("                        xy.x = document.documentElement.srollLeft;\n")
                .append("                        xy.y = document.documentElement.srollTop;\n")
                .append("                    }\n")
                .append("                    else if(document.body.srollLeft) {\n")
                .append("                        xy.x = document.body.srollLeft;\n")
                .append("                        xy.y = document.body.srollTop;\n")
                .append("                    }\n")
                .append("                    return xy;\n")
                .append("                }\n")
                .append("                \n")
                .append("                var content = document.getElementById('content');\n")
                .append("                opacity(content, 0.5);\n")
                .append("                \n")
                .append("                var viewPortWH = viewPortWidthHeight();\n")
                .append("                \n")
                .append("                content.style.width = viewPortWH.width + 'px';\n")
                .append("                content.style.paddingTop = viewPortWH.height / 4 + 'px'\n")
                .append("                content.style.height = viewPortWH.height / 2 + 'px';\n")
                .append("                \n")
                .append("                document.getElementById('viewButton').onclick = function() {\n")
                .append("                    window.location = \"/image/").append(timeStamp).append("\"\n")
                .append("                };\n")
                .append("                \n")
                .append("                document.getElementById('downloadButton').onclick = function() {\n")
//                .append("                    window.location = \"http:/").append(NetUtils.getLocalIPAddress()).append(":").append(NetUtils.PORT_SERVER).append("/download\"\n")
                .append("                    window.location = \"/image/").append(timeStamp).append("\"\n")
                .append("                };\n")
                .append("            };\n")
                .append("        </script>        \n")
                .append("    </head>\n")
                .append("<body>\n")
                .append("<div id=\"content\">\n")
                .append("    <img src=\"/image/ic_qr_code_web_pdf.PNG\" alt=\"ic_qr_code_web_pdf.PNG\" width=\"230\" height=\"235\">\n")
                .append("    <br></br>\n")
                .append("    <button id=\"viewButton\">View</button>")
                .append("    <br></br>\n")
                .append("    <button id=\"downloadButton\">Download</button>\n")
                .append("    <br/><br/>\n")
                .append("</div>\n")
                .append("\n");

        pdf_download_html.append("</body>\n")
                .append("</html>\n");

        return pdf_download_html;
    }

    private void createIndexHTML(String downloadHtmlName) {
        Log.d(TAG, "createIndexHTML");
        String indexHtmlName = "index.html";
        File index_file = new File(Environment.getExternalStorageDirectory().getPath() + screenshotFolderPath, indexHtmlName);
        StringBuilder index_html = new StringBuilder()
                .append("<!DOCTYPE html>\n")
                .append("<html>\n")
                .append("    <head>\n")
                .append("        <meta content=\"text/html; charset=UTF-8\" http-equiv=\"content-type\">\n")
                .append("        <style type=\"text/css\">\n")
                .append("            #content {\n")
                .append("                text-align: center;\n")
                .append("                font-size:30px;\n")
                .append("                vertical-align: middle;\n")
                .append("                color: #000000;\n")
                .append("                background-color: #ffffff;\n")
                .append("                width: 100px;\n")
                .append("                height: 50px;\n")
                .append("                position: absolute;\n")
                .append("                top: 0px;\n")
                .append("                left: 0px;\n")
                .append("            }\n")
                .append("            #fileLink {\n")
                .append("            \ttext-align: center;\n")
                .append("            \tfont-size:30px;\n")
                .append("                vertical-align: middle;\n")
                .append("            }\n")
                .append("        </style>\n")
                .append("        <script type=\"text/javascript\">\n")
                .append("            window.onload = function(event) {\n")
                .append("                function style(obj, prop) {\n")
                .append("                    if(window.getComputedStyle) {\n")
                .append("                        return window.getComputedStyle(obj, null)[prop];\n")
                .append("                    }\n")
                .append("                    else if(obj.currentStyle) {\n")
                .append("                        return obj.currentStyle[prop];\n")
                .append("                    }\n")
                .append("                    else {\n")
                .append("                        return null;\n")
                .append("                    }\n")
                .append("                }            \n")
                .append("                function opacity(element, value) {\n")
                .append("                    if(value === undefined) { \n")
                .append("                        var opt = style(element, 'opacity') \n")
                .append("                                     || style(element, 'filter');\n")
                .append("                        if(opt === '') {\n")
                .append("                            return 1;\n")
                .append("                        }\n")
                .append("                        if(opt.indexOf('alpha') !== -1)  {\n")
                .append("                            return opt.substring(14, opt.length - 1) / 100;\n")
                .append("                        }\n")
                .append("                        return parseFloat(opt);\n")
                .append("                    }\n")
                .append("                \n")
                .append("                } \n")
                .append("           \n")
                .append("                function screenWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: screen.width,\n")
                .append("                        height: screen.height\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function screenAvailWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: screen.availWidth,\n")
                .append("                        height: screen.availHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function windowXY() {\n")
                .append("                    var xy = {};\n")
                .append("                    if(window.screenX) {\n")
                .append("                        xy.x = window.screenX;\n")
                .append("                        xy.y = window.screenY;\n")
                .append("                    }\n")
                .append("                    else if(window.screenLeft) {\n")
                .append("                        xy.x = window.screenLeft;\n")
                .append("                        xy.y = window.screenTop;\n")
                .append("                    }\n")
                .append("                    return xy;\n")
                .append("                }\n")
                .append("                function windowWidthHeight() {\n")
                .append("                    var wh = {};\n")
                .append("                    if(window.outerWidth) {\n")
                .append("                        wh.width = window.outerWidth;\n")
                .append("                        wh.height = window.outerHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.offsetWidth) {\n")
                .append("                        wh.width = document.documentElement.offsetWidth;\n")
                .append("                        wh.height = document.documentElement.offsetHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.body.offsetWidth) {\n")
                .append("                        wh.width = document.body.offsetWidth;\n")
                .append("                        wh.height = document.body.offsetHeight;\n")
                .append("                    }\n")
                .append("                    return wh;\n")
                .append("                }                \n")
                .append("                function htmlWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: window.documentElement.scrollWidth,\n")
                .append("                        height: window.documentElement.scrollHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function bodyWidthHeight() {\n")
                .append("                    return {\n")
                .append("                        width: window.body.scrollWidth,\n")
                .append("                        height: window.body.scrollHeight\n")
                .append("                    };\n")
                .append("                }\n")
                .append("                function viewPortWidthHeight() {\n")
                .append("                    var wh = {};\n")
                .append("                    if(window.innerWidth) {\n")
                .append("                        wh.width = window.innerWidth;\n")
                .append("                        wh.height = window.innerHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.clientWidth) {\n")
                .append("                        wh.width = document.documentElement.clientWidth;\n")
                .append("                        wh.height = document.documentElement.clientHeight;\n")
                .append("                    }\n")
                .append("                    else if(document.body.clientWidth) {\n")
                .append("                        wh.width = document.body.clientWidth;\n")
                .append("                        wh.height = document.body.clientHeight;\n")
                .append("                    }\n")
                .append("                    return wh;\n")
                .append("                }\n")
                .append("                function scrollXY() {\n")
                .append("                    var xy = {};\n")
                .append("                    if(window.pageXOffset) {\n")
                .append("                        xy.x = window.pageXOffset;\n")
                .append("                        xy.y = window.pageYOffset;\n")
                .append("                    }\n")
                .append("                    else if(document.documentElement.srollLeft) {\n")
                .append("                        xy.x = document.documentElement.srollLeft;\n")
                .append("                        xy.y = document.documentElement.srollTop;\n")
                .append("                    }\n")
                .append("                    else if(document.body.srollLeft) {\n")
                .append("                        xy.x = document.body.srollLeft;\n")
                .append("                        xy.y = document.body.srollTop;\n")
                .append("                    }\n")
                .append("                    return xy;\n")
                .append("                }\n")
                .append("                \n")
                .append("                var content = document.getElementById('content');\n")
                .append("                opacity(content, 0.5);\n")
                .append("                \n")
                .append("                var viewPortWH = viewPortWidthHeight();\n")
                .append("                \n")
                .append("                content.style.width = viewPortWH.width + 'px';\n")
                .append("                content.style.paddingTop = viewPortWH.height / 4 + 'px'\n")
                .append("                content.style.height = viewPortWH.height / 4 + 'px';\n")
                .append("            };\n")
                .append("        </script>        \n")
                .append("    </head>\n")
                .append("    <body>\n")
                .append("        <div id=\"content\">\n")
                .append("            <h1>QR Code Service is running</h1>\n")
                .append("            <br></br>\n")
                .append("            <a id=\"fileLink\" href=\"").append(downloadHtmlName).append("\">").append(downloadHtmlName).append("</a>\n")
                .append("        </div>\n")
                .append("    </body>\n")
                .append("</html>");
        try {
            FileOutputStream out = new FileOutputStream(index_file);
            byte[] data = index_html.toString().getBytes();
            out.write(data);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "Save " + indexHtmlName + " fail:" + e.getMessage());
        }
    }

    private void createPDFFile(ArrayList<String> fileList) {
        PdfDocument document = new PdfDocument();//1, 建立PdfDocument
        FileHelper fileHelper = FileHelper.getInstance(this);
        for(String path: fileList) {
            Bitmap bitmap = BitmapFactory.decodeFile(fileHelper.getPreviewFile(path).getPath());
            Log.d(TAG, "createPDFFile: bitmap width height:"+bitmap.getWidth());
            PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo
                    .Builder(PDF_WIDTH, PDF_HEIGHT, fileList.size())
                    .create();//2 crate a page description
            PdfDocument.Page page = document.startPage(pageInfo); //3、start a page
            Canvas canvas = page.getCanvas();
            canvas.drawBitmap(bitmap,0,0,null);
            document.finishPage(page);
            bitmap.recycle();
        }

        File pdf_file = new File(saveFolder.getAbsolutePath() + String.format("/image/%s", timeStamp));
        try {
            document.writeTo(new FileOutputStream(pdf_file)); //write the document content
        } catch (IOException e) {
            e.printStackTrace();
        }

        document.close(); //close the document
        Log.i(TAG, "createPDFFile " + pdf_file.getName() + " is successful");
    }

//    private void createPDFFile(ArrayList<String> fileList) {
//        Log.d(TAG, "createPDFFile");
//        // crate one pdf download html
//        Document document = new Document();
//        String directoryPath = Environment.getExternalStorageDirectory() + "/Pictures/Screenshots";
//        try {
//            PdfWriter.getInstance(document, new FileOutputStream(directoryPath + "/image/download.pdf")); //  Change pdf's name.
//        } catch (DocumentException | FileNotFoundException e) {
//            e.printStackTrace();
//            Log.d(TAG, "create example pdf exception:" + e.getMessage());
//        }
//        document.open();
//
//        for(String path: fileList) {
//            String[] fileNameSplit = path.split("/");
//            String fileName = fileNameSplit[fileNameSplit.length-1];
//            Image image = null;
//            try {
//                image = Image.getInstance(directoryPath + "/image/" + path);
//            } catch (BadElementException | IOException e) {
//                e.printStackTrace();
//                Log.d(TAG, "open " + path + " image pdf exception:" + e.getMessage());
//            }
//            if(image!=null) {
//                float scale = ((document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin() - 0) / image.getWidth()) * 100;
//                image.scalePercent(scale);
//                image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP);
//            }
//            try {
//                float fntSize, lineSpacing;
//                fntSize = 30f;
//                lineSpacing = 15f;
//                Paragraph fileNameParagraph = new Paragraph(new Phrase(lineSpacing, fileName, FontFactory.getFont(FontFactory.COURIER, fntSize)));
//                fileNameParagraph.setAlignment(Element.ALIGN_CENTER);
//                document.add(new Paragraph("\n"));
//                document.add(image);
//                document.add(new Paragraph("\n"));
//                document.add(fileNameParagraph);
//                document.add(new Paragraph("\n"));
//            } catch (DocumentException e) {
//                e.printStackTrace();
//                Log.d(TAG, "add " + path + " image to pdf exception:" + e.getMessage());
//            }
//        }
//        document.close();
//    }

    private void createPDFImage() {
        Log.d(TAG, "createPDFImage");
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_qr_code_web_pdf);
        File file = new File(Environment.getExternalStorageDirectory()  + screenshotFolderPath +"/image", "ic_qr_code_web_pdf.PNG");
        FileOutputStream outStream = null;
        try {
            outStream = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.d(TAG, "createPDFImage is fail:" + e.getMessage());
        }
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
        try {
            assert outStream != null;
            outStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "createPDFImage is fail:" + e.getMessage());
        }
        try {
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "createPDFImage is fail:" + e.getMessage());
        }
    }

    private void deletePDFImage() {
        Log.d(TAG, "deletePDFImage");
        File PDFImageFile = new File(Environment.getExternalStorageDirectory() + screenshotFolderPath+ "/image", "ic_qr_code_web_pdf.PNG");
        if(PDFImageFile.exists()) {
            if(PDFImageFile.delete()) {
                Log.d(TAG, "delete ic_qr_code_web_pdf.PNG is success");
            } else {
                Log.e(TAG, "delete ic_qr_code_web_pdf.PNG is fail");
            }
        } else {
            Log.e(TAG, "delete ic_qr_code_web_pdf.PNG is fail");
        }
    }

    private void deleteHTMLFile() {
        Log.d(TAG, "deleteHTMLFile");
        //delete download html
        File downloadHTMLFile = new File(Environment.getExternalStorageDirectory().getPath() + screenshotFolderPath + "/download.html");
        if(downloadHTMLFile.exists()) {
            if (downloadHTMLFile.delete()) {
                Log.d(TAG, "delete download.html is success");
            } else {
                Log.e(TAG, "delete download.html is fail");
            }
        } else {
            Log.e(TAG, "download.html is not exist");
        }

        //delete index html
        File indexHTMLFile = new File(Environment.getExternalStorageDirectory().getPath() + screenshotFolderPath + "/index.html");
        if(indexHTMLFile.exists()) {
            if (indexHTMLFile.delete()) {
                Log.d(TAG, "delete index.html is success");
            } else {
                Log.e(TAG, "delete index.html is fail");
            }
        } else {
            Log.e(TAG, "index.html is not exist");
        }
    }

    private void deletePDFFile() {
        Log.d(TAG, "deletePDFFile");

        //delete download pdf
        File downloadHTMLFile = new File(Environment.getExternalStorageDirectory().getPath() + screenshotFolderPath + "/image/download.pdf");
        if (downloadHTMLFile.exists()) {
            if (downloadHTMLFile.delete()) {
                Log.d(TAG, "delete download.pdf is success");
            } else {
                Log.e(TAG, "delete download.pdf is fail");
            }
        } else {
            Log.e(TAG, "download.pdf is not exist");
        }
    }

    private void setDeleteJpegFile() {
        Log.d(TAG, "setDeleteJpegFile");
        while (deleteJpegList.size() > 0){
            String path = deleteJpegList.poll();
            if (path != null && !path.isEmpty()) {
                File file = new File(path);
                Log.d(TAG, "delete path : " + path);
                if (file.delete()) {
                    Log.d(TAG, "delete done");
//                    MediaScannerConnection.scanFile(this, new String[] {path}, null, null);
                }
            }
        }
    }
}